package com.bigdata.sql

import org.apache.spark.sql.expressions.UserDefinedFunction
import org.apache.spark.sql.{DataFrame, SparkSession}

/**
 * Hive怎么添加自定义函数？
 * 1.先编写函数代码，
 * 2.打包，
 * 3.上传到Hive安装路径下的lib中，
 * 4.使用命令添加函数
 * Spark UDF：用户自定义函数
 */
object Demo13UDF {
  def main(args: Array[String]): Unit = {
    val spark: SparkSession = SparkSession
      .builder()
      .master("local")
      .appName("Demo13UDF")
      .config("spark.sql.shuffle.partitions", 1)
      .getOrCreate()
    import org.apache.spark.sql.functions._
    import spark.implicits._

    /**
     * 1、DSL自定义函数
     * 函数： 参数 -》 返回值
     * 在自定义函数中可以编写scala代码
     * 函数的参数不止有一个，具体有几个看具体的需求
     */
    val strLenFun = (str: String) => {
      // 反转字符串，并且拼接长度
      str.reverse.concat(str.length.toString)
    }
    // 返回一个spark中可以使用的函数
    val str_len: UserDefinedFunction = udf(strLenFun)


    val studentDF: DataFrame = spark
      .read
      .format("json")
      .load("data/students.json")

    //使用自定义函数
    studentDF
      .select(str_len($"name") as "p_class")
    // .show()

    /**
     * 2、SQL 自定义函数
     */
    //在sql中使用自定义函数需要注册
    spark.udf.register("str_len", str_len)
    // 注册临时表
    studentDF.createOrReplaceTempView("student")

    // 自定义函数，在SQL中使用的频率更高
    spark
      .sql(
        """
          |select *, str_len(name) as pro_name from student
          |""".stripMargin)
      .show()


    /**
     * 3、在Spark-sql命令行中使用hive的自定义函数
     * 1、写一个hive的自定义函数
     * 2、将类打包上传到spark 的jars目录下 /usr/local/soft/spark-2.4.5/jars
     * 3、进入到spark-sql的命令行创建一个自定义函数
     * create function str_len as 'com.spark.sql.Demo14StrLeb';
     */

  }

}
